package rpt.yto.flex.remote.data.biz;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import net.sf.json.JSONArray;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import rpt.yto.flex.remote.data.bean.StatisticB2Bean;
import rpt.yto.flex.remote.data.bean.StatisticB3Bean;
import rpt.yto.flex.remote.data.bean.StatisticB4Bean;
import rpt.yto.flex.remote.data.bean.StatisticB5Bean;
import rpt.yto.flex.remote.data.bean.StatisticBBean;
import rpt.yto.flex.remote.data.dao.IQueryDAO;
import rpt.yto.flex.remote.data.dao.processor.Query_allpsn;
import rpt.yto.flex.remote.data.dao.processor.Query_allpsn_dept;
import rpt.yto.flex.remote.data.dao.processor.Query_allpsn_mng;
import rpt.yto.flex.remote.data.dao.processor.Query_allpsn_province;
import rpt.yto.flex.remote.data.dao.processor.Query_allpsnchange;
import rpt.yto.flex.remote.data.dao.processor.Query_deptpsn;
import rpt.yto.flex.remote.data.dao.processor.Query_dirpsn;
import rpt.yto.flex.remote.data.dao.processor.Query_dirpsn_corp;
import rpt.yto.flex.remote.data.dao.processor.Query_dirpsn_province_center;
import rpt.yto.flex.remote.data.dao.processor.Query_headpsn;
import rpt.yto.flex.remote.data.dao.processor.Query_joinpsn_center;
import rpt.yto.flex.remote.data.dao.processor.Query_joinpsn_corp;
import rpt.yto.flex.remote.data.dao.processor.Query_psnchange;
import rpt.yto.flex.remote.data.dao.processor.Query_totalpsn;
import rpt.yto.util.beans.SuperBean;

@SuppressWarnings("unchecked")
public class QueryBiz {
	
	private static ApplicationContext context;
	private static IQueryDAO queryDAO;
	private List<Map<String , Object>> results;
	private static QueryBiz queryBiz = new QueryBiz();
	
	private static Map<String , Integer> billtype = null;
	
	public QueryBiz() {
		
	}
	
	public static QueryBiz getInstance() {
		return queryBiz;
	}
	
	static {
		context = new ClassPathXmlApplicationContext("applicationContext.xml");
		queryDAO = (IQueryDAO) context.getBean("queryDAO");
		
		initBillTypeMap();
		
	}
	
	private static final void initBillTypeMap() {
		
		billtype = new ConcurrentHashMap<String , Integer>();
		billtype.put("allpsn", 1);
		billtype.put("allpsn.dept", 2);
		billtype.put("allpsn.mng", 3);
		billtype.put("allpsn.province", 4);
		billtype.put("headpsn", 5);
		billtype.put("deptpsn", 6);
		billtype.put("dirpsn.province", 7);
		billtype.put("dirpsn.center", 8);
		billtype.put("dirpsn.corp", 9);
		billtype.put("joinpsn.center", 10);
		billtype.put("joinpsn.corp", 11);
		billtype.put("dirpsn" , 12);
		billtype.put("rpt.totalpsn", 13);
		billtype.put("rpt.psnchange", 14);
		billtype.put("rpt.allpsnchange", 15);
		
	}

	public List<Map<String , Object>> executeQuery(String sql , Class beanType) throws Exception {
	
		List<Object> resultList = queryDAO.executeQuery(sql, beanType);
		
		if(resultList == null || resultList.size() == 0)
			return null;
		
		List<Map<String , Object>> resultMapList = new ArrayList<Map<String , Object>>();
		
		for(Object result : resultList) {
			
			Map<String , Object> resultMap = new ConcurrentHashMap<String , Object>();
			String[] keys = ((SuperBean) result).getAttributeNames();
			for(String key : keys) {
				try {
					resultMap.put(key, ((SuperBean) result).getAttributeValue(key));
				} catch(Exception e) {
					continue;
				}
			}
			
			resultMapList.add(resultMap);
		}
		
		return resultMapList;
			
		
		
	}
	
	public String executeQuery(String period , String type) throws Exception {
		
		try {
			String sql = " ";
			Class beanType = null;
			
			switch (billtype.get(type)) {
				case 1 :
					sql = Query_allpsn.getInstance().getQuerySQL(period);
					beanType = StatisticBBean.class;
					break;
					
				case 2 : 
					sql = Query_allpsn_dept.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 3 : 
					sql = Query_allpsn_mng.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 4 :
					sql = Query_allpsn_province.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 5 :
					sql = Query_headpsn.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 6 :
					sql = Query_deptpsn.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 7 :
					sql = Query_dirpsn_province_center.getInstance().getQuerySQLByType0(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 8 :
					sql = Query_dirpsn_province_center.getInstance().getQuerySQLByType1(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 9 : 
					sql = Query_dirpsn_corp.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 10 : 
					sql = Query_joinpsn_center.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					break;
					
				case 11 :
					
//					if(Query_joinpsn_corp.getInstance().distinctionMap == null)
//						Query_joinpsn_corp.getInstance().initDistinctionMap();
//					
//					Iterator iter = Query_joinpsn_corp.getInstance().distinctionMap.entrySet().iterator();
//					
//					List<Object> resultList = new ArrayList<Object>();
//					
//					while(iter.hasNext()) {
//					
//						Entry entry = (Entry) iter.next();
//						
//						String pk_corp = (String) entry.getKey();
//						
//						String[] vals = ConvertFunc.getInstance().change(entry.getValue()).split("~");
//						
//						Integer rowno = Integer.valueOf(vals[0]);
//						
//						String statistictype = vals[1];
//						
//						sql = Query_joinpsn_corp.getInstance().getQueryTypeByMap(period, pk_corp, rowno, statistictype);
//
//						List<Object> tmpList = queryDAO.executeQuery(sql, StatisticB2Bean.class);
//						
//						if(tmpList != null && tmpList.size() > 0) 
//							resultList.addAll(tmpList);
//						
//					}
//					
//					if(resultList != null && resultList.size() > 0) {
//						results = new ArrayList<Map<String , Object>>();
//						
//						for(Object table : resultList) {
//							results.add(((SuperBean)table).getBeanToMap());
//						}
//						
//						return JSONArray.fromObject(results).toString();
//						
//					}
//					
//					return "false";
					
					sql = Query_joinpsn_corp.getInstance().getQuerySQL(period);
					beanType = StatisticB2Bean.class;
					
					break;
				case 12 :
					sql = Query_dirpsn.getInstance().getQuerySQL();
					beanType = StatisticB3Bean.class;
					break;
					
				case 13 :
					sql = Query_totalpsn.getInstance().getQuerySQL(period);
					beanType = StatisticB4Bean.class;
					break;
					
				case 14 : 
					sql = Query_psnchange.getInstance().getQuerySQL(period);
					beanType = StatisticB5Bean.class;
					break;
					
				case 15 : 
					sql = Query_allpsnchange.getInstance().getQuerySQL(period);
					beanType = StatisticB5Bean.class;
					
				default:
					break;
			}
			
			if(beanType == null)
				return "false";
			
			List<Object> resultList = queryDAO.executeQuery(sql, beanType);
			
			if(resultList != null && resultList.size() > 0) {
				results = new ArrayList<Map<String , Object>>();
				
				resultList = postProcessing(resultList , billtype.get(type) , beanType);
				
				for(Object table : resultList) {
					results.add(((SuperBean)table).getBeanToMap());
				}
				
				return JSONArray.fromObject(results).toString();
				
			}
		} catch(Exception e) {
			e.printStackTrace();
			return "false";
		}
		
		return "false";
		
	}
	
	private final List<Object> postProcessing(List<Object> resultList , Integer type , Class cls) throws Exception {
		
		SuperBean allBean = (SuperBean) cls.newInstance();
		SuperBean rowOneBean = null;
		List<Object> newResultList = new ArrayList<Object>();
		
		switch(type) {
			case 1:
			case 2:
				
				SuperBean workingunitBean = (SuperBean) cls.newInstance();
				SuperBean joinBean = null;
				
				SuperBean rowTwoBean = null;
				
				
				
				for(Object table : resultList) {
					SuperBean bean = (SuperBean) table;
					if((Integer) bean.getAttributeValue("rowno") >= 3 && (Integer) bean.getAttributeValue("rowno") <= 7) {
						
						for(String attr : bean.getAttributeNames()) {
							
							if(bean.getAttributeValue(attr) instanceof Integer) {
								if(attr == "rowno") {
									workingunitBean.setAttributeValue(attr, 2);
									continue;
								}
								
								if(attr == "dr") {
									workingunitBean.setAttributeValue(attr, 0);
									continue;
								}
								
								workingunitBean.setAttributeValue(attr, (Integer)workingunitBean.getAttributeValue(attr) + (Integer)bean.getAttributeValue(attr));
								
							} else 
								workingunitBean.setAttributeValue(attr, rowTwoBean.getAttributeValue(attr));
						}
						
					} else if((Integer) bean.getAttributeValue("rowno") == 8)
						joinBean = bean;
					else if((Integer) bean.getAttributeValue("rowno") == 1)
						rowOneBean = bean;
					else if((Integer) bean.getAttributeValue("rowno") == 2)
						rowTwoBean = bean;
					
				}
				
				for(String attr : allBean.getAttributeNames()) {
					
					if(allBean.getAttributeValue(attr) instanceof Integer) {
						if(attr == "rowno") {
							allBean.setAttributeValue("rowno", 1);
							continue;
						}
						
						if(attr == "dr") {
							allBean.setAttributeValue("dr", 0);
							continue;
						}
						
						allBean.setAttributeValue(attr, (Integer)workingunitBean.getAttributeValue(attr) + (Integer)joinBean.getAttributeValue(attr));
						
					} else 
						allBean.setAttributeValue(attr, rowOneBean.getAttributeValue(attr));
					
				}
				
				for(Object table : resultList) {
					
					if((Integer)((SuperBean) table).getAttributeValue("rowno") == 1)
						newResultList.add(allBean);
					
					else if((Integer)((SuperBean) table).getAttributeValue("rowno") == 2)
						newResultList.add(workingunitBean);
					
					else 
						newResultList.add(table);
				}
				
				return newResultList;
				
			case 3 :
			case 4 :
				
				for(Object table : resultList) {
					SuperBean bean = (SuperBean) table;
					if((Integer) bean.getAttributeValue("rowno") > 1) {
						
						for(String attr : bean.getAttributeNames()) {
							
							if(bean.getAttributeValue(attr) instanceof Integer) {
								if(attr == "rowno") {
									allBean.setAttributeValue(attr, 1);
									continue;
								}
								
								if(attr == "dr") {
									allBean.setAttributeValue(attr, 0);
									continue;
								}
								
								allBean.setAttributeValue(attr, (Integer)allBean.getAttributeValue(attr) + (Integer)bean.getAttributeValue(attr));
								
							} else 
								allBean.setAttributeValue(attr, rowOneBean.getAttributeValue(attr));
						}
						
					} else if((Integer) bean.getAttributeValue("rowno") == 1)
						rowOneBean = bean;
					
				}
				
				for(Object table : resultList) {
					
					if((Integer)((SuperBean) table).getAttributeValue("rowno") == 1)
						newResultList.add(allBean);
					
					else 
						newResultList.add(table);
					
				}
				
				return newResultList;
				
			default :
				break;
		}
		
		return resultList;
		
	}
	
}
